#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <pthread.h>
#include <sys/time.h>

#define DEFAULT_ADDRESS "127.0.0.1"
#define DEFAULT_PORT	4444
#define MAX_BUFF_SIZE   1500
#define MAX_CMD_SIZE 128

#define GUARD_TIME_US 100
#define TIME_CORRECTION_US -18
#define BITRATE 48000000

#define PACKET_PER_BUFFER 7
#define TS_SIZE 188

#define SEND_PERIOD_US 200

#define OK 0
#define ERROR -1

static pthread_t ThreadId;
static int ThreadLoop = 1;
static void * SenderThread(void * Arg);
static char * InetAddr = INADDR_ANY;
static int InetPort = DEFAULT_PORT;
static int SendSock = 0;

static void Send(void);

static char * FileName = NULL;
static FILE * File = NULL;


// Test buffers
unsigned char DummyBuffer[] =
{
	0x47, 0x60, 0x00, 0x10, 0x00, 0x00, 0xb0, 0x0d,
	0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x20, 0xf9, 0x62, 0xf5, 0x8b, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0x47, 0x60, 0x20, 0x10, 0x00, 0x02, 0xb0, 0x1d, 0x00, 0x01, 0xc1, 0x00,
	0x00, 0xe0, 0x30, 0xf0, 0x00, 0x02, 0xe0, 0x31, 0xf0, 0x03, 0x52, 0x01, 0x00, 0x81, 0xe0, 0x32,
	0xf0, 0x03, 0x52, 0x01, 0x10, 0x20, 0x9a, 0xa3, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0x47, 0x00, 0x30, 0x20, 0xb7, 0x10, 0x00, 0x00, 0xe1, 0xd5, 0xfe, 0xc0, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x47, 0x1f, 0xff, 0x10,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x47, 0x1f, 0xff, 0x10, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0x47, 0x1f, 0xff, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0x47, 0x1f, 0xff, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

int main(int argc, char *argv[])
{
    int c = 0;
    opterr = 0;
    char Command[MAX_CMD_SIZE];
    unsigned int opt = 1;


   // Parse option
    while ((c = getopt (argc, argv, "a:p:f:h")) != -1)
    {
		switch (c)
		{
		case 'a':
			if (optarg) InetAddr = optarg;
		break;

		case 'p':
			if (optarg) InetPort = atoi(optarg);
		break;

		case 'f':
			if (optarg) FileName = optarg;
		break;

		case 'h':
			printf("\n"
				  "Client [options]\n"
				  "\tOptions:\n"
				  "\t\t-a  address       internet address, dotted-string"
				  "\t\t-p  port          port number"
			      "\t\t-f  file          File to read");
		break;

		default:
			break;
		}
    }

    // Open file to read
	if (FileName != NULL)
	{
		File = fopen(FileName, "r");
		if (File == NULL)
		{
			return(-1);
		}
	}
	else
	{
		return(-1);
	}

    // Create socket
    SendSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (SendSock < 0)
    {
    	return(-1);
    }

    if (setsockopt(SendSock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1)
    {
    	return(-1);
    }

	printf("UDP socket open to %s:%d\n", InetAddr, InetPort);

	// CLI process
	while (1)
	{
		// Get the command
		printf("Command: ");
		scanf ("%s", Command);

		// Parse the command
		if (strcmp("quit", Command) == 0)
		{
			break;
		}

		if (strcmp("help", Command) == 0)
		{
			printf(	"help - to get the list of internal command\n"
					"quit - to quit this CLI without closing the server\n"
					"send - Send a packet to the server\n"
					);
			continue;
		}

		if (strcmp("send", Command) == 0)
		{
			// Start server thread
			Send();
			continue;
		}
		if (strcmp("sendt", Command) == 0)
		{
			// Start server thread
			if (pthread_create(&ThreadId, NULL, SenderThread, NULL) != 0)
			{
				return -1;
			}
			continue;
		}
	}

	ThreadLoop = 0;
	shutdown(SendSock, SHUT_RDWR);
	close(SendSock);
	SendSock = 0;

	if (File != NULL)
	{
		fclose(File);
		File = NULL;
	}

	pthread_join(ThreadId, NULL);

	printf("Bye bye!\n");

	return 0;
}

void * SenderThread(void * Arg)
{
	struct sockaddr_in RemoteAddr;
	double NewTime = 0.0;
	double NextTime = 0.0;
	struct timeval InitTVal;

	unsigned char Buffer[MAX_BUFF_SIZE];
	int BuffSize = sizeof(DummyBuffer);

	gettimeofday(&InitTVal, NULL);

	bzero((char *) &RemoteAddr, sizeof(RemoteAddr));
	RemoteAddr.sin_family = AF_INET;
	RemoteAddr.sin_addr.s_addr = inet_addr(InetAddr);
	RemoteAddr.sin_port = htons(InetPort);

	while (ThreadLoop)
	{
		// Wait the before sending the next packet
#define GUARD_TIME_US 100
#define TIME_CORRECTION_US -18
		do
		{
			struct timeval TVal;
			gettimeofday(&TVal, NULL);
			NewTime = (double)(TVal.tv_sec-InitTVal.tv_sec) + ((double)(TVal.tv_usec-InitTVal.tv_usec) / 1000000);
//			if (NewTime < (NextTime-GUARD_TIME_US))
//			{
//				usleep((unsigned int)(NextTime-GUARD_TIME_US-NewTime)*1000000);
//			}
		} while (NewTime < NextTime);

		// Send
	    bzero((void *)Buffer, MAX_BUFF_SIZE);
	    strncpy((char*)Buffer, (char*)DummyBuffer, sizeof(DummyBuffer));

		int Count = sendto(SendSock, (void *)Buffer, BuffSize, 0, (struct sockaddr*) &RemoteAddr, (socklen_t) sizeof(struct sockaddr_in));
		if (Count <= 0)
		{
	    	pthread_exit(NULL);
		}

	    //printf("Sent %i bytes\n", Count);

		// Calculate next time
		NextTime = NewTime + (double)(SEND_PERIOD_US + TIME_CORRECTION_US)/1000000 ;

	}

	pthread_exit(NULL);
	return(NULL);
}


static void Send(void)
{
	struct sockaddr_in RemoteAddr;
	double NewTime = 0.0;
	double NextTime = 0.0;
	struct timeval InitTVal;
	struct timeval TVal;
	struct timeval NextTVal;
	double bitrate = 48000000;
	double bitrateout;
	unsigned long long PacketsSent = 0;
	unsigned int InBetweenPck = 219;

	unsigned char Buffer[MAX_BUFF_SIZE];
	int ReadCount = 1;

	NextTVal.tv_sec = 0;
	NextTVal.tv_usec = 0;

	gettimeofday(&InitTVal, NULL);

	bzero((char *) &RemoteAddr, sizeof(RemoteAddr));
	RemoteAddr.sin_family = AF_INET;
	RemoteAddr.sin_addr.s_addr = inet_addr(InetAddr);
	RemoteAddr.sin_port = htons(InetPort);

	while (ReadCount > 0)
	{
		// Get data from file
		bzero((void *)Buffer, MAX_BUFF_SIZE);
		ReadCount = fread((void*)Buffer, 1, PACKET_PER_BUFFER*TS_SIZE, File);
		if (ReadCount > 0)
		{
			unsigned int Size = ReadCount;

			// Wait the before sending the next packet
#ifdef TSPLAY
		      while (1)
		      {
				struct timeval TVal;
		        gettimeofday(&TVal,NULL);
		        timersub(&TVal,&InitTVal,&TVal);

		        /* time is now elapsed time since start */

		        bitrateout = ((double)PacketsSent * (double)TS_SIZE * 8.) / ((double)TVal.tv_sec + (TVal.tv_usec / 1000000.));

		        if (bitrateout<=bitrate)
		        {
		          break;
		        }

		        /* wait one half packet period */
//		        nanosleep(&sHalfPacketPeriod,NULL);
		      }
#else
			do
			{
				gettimeofday(&TVal, NULL);
				timersub(&TVal, &InitTVal, &TVal);
			} while (timercmp(&TVal, &NextTVal, <));
#endif

			// Send
			int Count = sendto(SendSock, (void *)Buffer, Size, 0, (struct sockaddr*) &RemoteAddr, (socklen_t) sizeof(struct sockaddr_in));
			if (Count <= 0)
			{
		    	break;
			}
			PacketsSent += ReadCount/TS_SIZE;

			// Calculate next time
			struct timeval TempVal;
			TempVal.tv_sec = InBetweenPck/1000000;
			TempVal.tv_usec = InBetweenPck%1000000;
			timeradd(&NextTVal, &TempVal, &NextTVal);

			//NextTime = NewTime + ((double)(Size*8) / BITRATE) + ((double)TIME_CORRECTION_US/1000000);
		}

		if ((ReadCount <= 0) || (feof(File)))
		{
			// Error
			break;
		}
	}
}

